package com.yfp.client.service.impl;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yfp.client.domain.*;
import com.yfp.client.domain.*;
import com.yfp.client.domain.dto.SettleDTO;
import com.yfp.client.enums.ClientCouponSourceEnums;
import com.yfp.client.enums.CouponPackShopStatusEnum;
import com.yfp.client.mapper.ClientCouponMapper;
import com.yfp.client.mapper.MarCouponPackShopMapper;
import com.yfp.client.service.*;
import com.yfp.client.service.*;
import com.yfp.client.util.RedisDistributedLock;
import com.yfp.client.util.RedisKey;
import com.yfp.client.util.ResponseEnum;
import com.yfp.common.core.constant.CacheConstants;
import com.yfp.common.core.domain.R;
import com.yfp.common.core.enums.PayStatusEnum;
import com.yfp.common.core.utils.DateUtils;
import com.yfp.operation.api.RemoteOperationService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 *
 * @description 针对表【mar_coupon_pack_shop(礼包销售)】的数据库操作Service实现
 * @createDate 2024-10-22 09:53:40
 */
@Slf4j
@Service
public class MarCouponPackShopServiceImpl extends ServiceImpl<MarCouponPackShopMapper, MarCouponPackShop> implements MarCouponPackShopService {

    @Resource
    private MarCouponService marCouponService;
    @Resource
    public RedisTemplate redisTemplate;
    @Resource
    private MarCouponPackService marCouponPackService;
    @Resource
    private MarCouponPackDetailsService marCouponPackDetailsService;
    @Resource
    private MarCouponPackShopMapper marCouponPackShopMapper;
    @Resource
    private ClientCouponMapper clientCouponMapper;
    @Resource
    private OrderComboService orderComboService;
    @Resource
    private OrderListService orderListService;
    @Resource
    private RemoteOperationService remoteOperationService;

    @Override
    public List<MarCouponPackShop> listByStatus(Integer status, String cityName) {
        return marCouponPackShopMapper.listByStatus(status, cityName);
    }

    @Override
    public void decreaseStockQuantity(SettleDTO comboDTOS) {
        Long packShopId = comboDTOS.getId();
        MarCouponPackShop marCouponPackShop = marCouponPackShopMapper.selectById(packShopId);

        // 校验库存
        Assert.notNull(marCouponPackShop, "当前礼包已下架");
        Assert.isFalse(marCouponPackShop.getCurrentStock() < comboDTOS.getNum(), "库存不足");

        marCouponPackShop.setCurrentStock(marCouponPackShop.getCurrentStock() - comboDTOS.getNum());

        this.updateCurrentStockById(marCouponPackShop);
    }

    @Override
    public void updateCurrentStockById(MarCouponPackShop newStocks) {
        marCouponPackShopMapper.updateCurrentStockById(newStocks);
    }

    @Override
    public void updateCurrentStockAndPackNumByIds(List<MarCouponPackShop> newStocks) {
        marCouponPackShopMapper.updateCurrentStockAndPackNumByIds(newStocks);
    }

    @Override
    public void recoverStockQuantity(OrderCombo orderCombo, List<OrderDetail> orderDetails) {
        List<Long> packageIds = orderDetails.stream().map(item -> Long.parseLong(item.getPackageId())).collect(Collectors.toList());

        List<MarCouponPackShop> marCouponPackShops = marCouponPackShopMapper.selectBatchIds(packageIds);
        Map<Long, MarCouponPackShop> couponPackShopMapById = marCouponPackShops.stream().collect(Collectors.toMap(MarCouponPackShop::getId, item -> item));

        Map<String, Long> detailsMapByPackageId = orderDetails.stream().collect(Collectors.groupingBy(OrderDetail::getPackageId, Collectors.summingLong(OrderDetail::getCount)));
        List<MarCouponPackShop> newStocks = detailsMapByPackageId.entrySet().stream().map(entry -> {
            Long packageId = Long.parseLong(entry.getKey());
            Long quantity = entry.getValue();
            MarCouponPackShop marCouponPackShop = couponPackShopMapById.getOrDefault(packageId, new MarCouponPackShop());
            if (
                    (marCouponPackShop.getPackNum() >= (marCouponPackShop.getCurrentStock() + marCouponPackShop.getSoldQuantity() + quantity))
                            && (marCouponPackShop.getStatus() == 1 || marCouponPackShop.getStatus() == 0)) {
                // 上架中的状态归还库存
//                marCouponPackShop.setPackNum(marCouponPackShop.getPackNum());
                marCouponPackShop.setCurrentStock((Optional.ofNullable(marCouponPackShop.getCurrentStock()).orElse(0L) + quantity));
                log.info("礼包套餐id:{},补充后数量:{}", packageId, marCouponPackShop.getCurrentStock());
            } else {
                // 未上架的状态归还礼包库存
                Long couponPackId = marCouponPackShop.getCouponPackId();
                MarCouponPack marCouponPack = marCouponPackService.findById(couponPackId);
                marCouponPack.setSurplusCount(marCouponPack.getSurplusCount() + quantity.intValue());
                marCouponPackService.editSurplusCountById(couponPackId, marCouponPack.getSurplusCount());
            }
            return marCouponPackShop;
        }).collect(Collectors.toList());

        this.updateCurrentStockAndPackNumByIds(newStocks);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void giveCoupon(String userId, Long packShopId) {
        log.info("giveCoupon:用户id:{},礼包id:{}", userId, packShopId);
        R<Void> voidR = remoteOperationService.checkCouponPackAndUpdateAllStatus();
        RedisDistributedLock redisDistributedLock = new RedisDistributedLock(redisTemplate, CacheConstants.MAR_COUPON_PACK_SOLD_QUANTITY_LOCK_KEY + packShopId, 10);
        try {
            // 加锁
            redisDistributedLock.lock();
            MarCouponPackShop marCouponPackShop = marCouponPackShopMapper.selectById(packShopId);
            MarCouponPack marCouponPack = marCouponPackService.findById(marCouponPackShop.getCouponPackId());

            log.info("giveCoupon:状态:{}", marCouponPack.getStatus());
            if (marCouponPack.getStatus() != 1) {
                return;
            }

            List<MarCouponPackDetails> marCouponPackDetails = marCouponPackDetailsService.findByCouponPackId(marCouponPack.getId());
            for (MarCouponPackDetails marCouponPackDetail : marCouponPackDetails) {
                MarCoupon marCoupon = marCouponService.findById(marCouponPackDetail.getCouponId());
                log.info("giveCoupon:marCoupon_id:{}", marCoupon.getId());
                for (int i = 0; i < marCouponPackDetail.getCouponCount(); i++) {
                    ResponseEnum responseEnum = this.verifyCoupon(marCoupon.getId(), userId, marCouponPack.getId());
                    log.info("giveCoupon:" + responseEnum.getMsg());
                }
            }
        } catch (InterruptedException e) {
            log.info("出现异常， 异常信息：{}", e.getMessage());
        } finally {
            redisDistributedLock.unlock();
        }
    }

    @Override
    public ResponseEnum verifyCouponBoolean(Long couponId, Long couponPackId, String clientId) {

        MarCoupon marCoupon = marCouponService.findById(couponId);
        if (null != marCoupon.getValidDays() && marCoupon.getValidDays() != 0) {
            // 当前日期
            LocalDate currentDate = LocalDate.now();
            // 要添加的天数
            int daysToAdd = marCoupon.getValidDays();
            // 当前日期加上指定天数
            LocalDate newDate = currentDate.plusDays(daysToAdd);
            // 获取结果日期的起始时间（00:00:00）
            LocalDateTime startOfDay = newDate.atStartOfDay();
            LocalDateTime localDateTime = startOfDay.minusSeconds(1);
            Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
            // 转换为 Date
            Date date = Date.from(instant);
            marCoupon.setValidStartTime(new Date());
            marCoupon.setValidEndTime(date);
        }
        // 优惠券不存在
        // if (null == marCoupon) {
        //     log.info("优惠券不存在");
        //     return false;
        // }
        // // 优惠券删除或者优惠券失效
        // if (marCoupon.getStatus() == 0 || marCoupon.getStatus() == 2) {
        //     log.info("优惠券删除或者优惠券失效");
        //     return false;
        // }
        // 优惠券是否过期
        // Date date = DateUtils.addDays(marCoupon.getValidEndTime(), marCoupon.getPostponeDay());
        // if (date.getTime() < System.currentTimeMillis()) {
        //     log.info("优惠券已过期");
        //     return false;
        // }
        // 优惠券剩余数量不足
        // if (marCoupon.getSurplusCount() == 0) {
        //     log.info("优惠券剩余数量不足");
        //     return false;
        // }
        // 最大领取
        int countCoupon = clientCouponMapper.countByClientIdAndCouponId(clientId, couponId, null);
        if (countCoupon >= marCoupon.getReceiveCount()) {
            return ResponseEnum.COUPON_COUNT_EXCEED;
        }
        // 是否新用户
        // if (marCoupon.getClientStatus() == 2) {
        //     Integer orderCount = orderComboService.countOrderByClientId(clientId);
        //     if (orderCount > 0) {
        //         log.info("非新用户");
        //         return false;
        //     }
        // }
        // 礼包赠券数限制
        // int countCouponPack = clientCouponMapper.countByCouponPackIdAndClientIdInt(couponPackId, clientId);
        // if (countCouponPack > 0) {
        //     return ResponseEnum.COUPON_COUNT_EXCEED;
        // }
        return ResponseEnum.OPERATOR_SUCCESS;
    }

    @Override
    public ResponseEnum verifyCoupon(Long couponId, String clientId, Long couponPackId) {
        RedisDistributedLock redisDistributedLock = new RedisDistributedLock(redisTemplate, RedisKey.COUPONLOCK, 10);
        try {
            // 加锁
            redisDistributedLock.lock();

            MarCoupon marCoupon = marCouponService.findById(couponId);
            if (null != marCoupon.getValidDays() && marCoupon.getValidDays() != 0) {
                // 当前日期
                LocalDate currentDate = LocalDate.now();
                // 要添加的天数
                int daysToAdd = marCoupon.getValidDays();
                // 当前日期加上指定天数
                LocalDate newDate = currentDate.plusDays(daysToAdd);
                // 获取结果日期的起始时间（00:00:00）
                LocalDateTime startOfDay = newDate.atStartOfDay();
                LocalDateTime localDateTime = startOfDay.minusSeconds(1);
                Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
                // 转换为 Date
                Date date = Date.from(instant);
                marCoupon.setValidStartTime(new Date());
                marCoupon.setValidEndTime(date);
            }
            // 优惠券不存在
            if (null == marCoupon) {
                return ResponseEnum.COUPON_NOT_EXIST;
            }
            // 优惠券删除或者优惠券失效
            if (marCoupon.getStatus() == 0 || marCoupon.getStatus() == 2) {
                return ResponseEnum.COUPON_LOSE_EFFICACY;
            }
            // 优惠券是否过期
            Date date = DateUtils.addDays(marCoupon.getValidEndTime(), marCoupon.getPostponeDay());
            if (date.getTime() < System.currentTimeMillis()) {
                return ResponseEnum.COUPON_OVERDUE;
            }
            // 优惠券剩余数量不足
            if (marCoupon.getSurplusCount() == 0) {
                return ResponseEnum.COUPON_NOT_SURPLUS_COUNT;
            }
            // 最大领取
            int countCoupon = clientCouponMapper.countByClientIdAndCouponId(clientId, couponId, null);
            if (countCoupon >= marCoupon.getReceiveCount()) {
                return ResponseEnum.COUPON_COUNT_EXCEED;
            }
            // 是否新用户
            if (marCoupon.getClientStatus() == 2) {
                Integer orderCount = orderComboService.countOrderByClientId(clientId);
                if (orderCount > 0) {
                    return ResponseEnum.COUPON_NEW_CLIENT;
                }
            }
            marCouponService.editSurplusCount(marCoupon.getId());

            ClientCoupon clientCoupon = new ClientCoupon();
            BeanUtils.copyProperties(marCoupon, clientCoupon);
            clientCoupon.setClientId(clientId);
            clientCoupon.setCouponId(couponId);
            clientCoupon.setCouponPackId(couponPackId);
            clientCoupon.setSourceType(ClientCouponSourceEnums.BUY_GIFT_PACKAGE.getCode());
            clientCouponMapper.insert(clientCoupon);

            return ResponseEnum.OPERATOR_SUCCESS;
        } catch (Exception e) {
            e.printStackTrace();
            log.info("领券异常：{}", e.getMessage());
        } finally {
            redisDistributedLock.unlock();
        }
        return ResponseEnum.OPERATOR_FAILUER;
    }

    @Override
    public void addSoldQuantity(Long id) {
        MarCouponPackShop marCouponPackShop = marCouponPackShopMapper.selectById(id);
        marCouponPackShop.setSoldQuantity(marCouponPackShop.getSoldQuantity() + 1);

        marCouponPackShopMapper.updateById(marCouponPackShop);
    }

    @Override
    public void updateStatusToSoldOut(Long id) {

        MarCouponPackShop marCouponPackShop = marCouponPackShopMapper.selectById(id);
        // 礼包实时库存为0
        if (!NumberUtil.equals(marCouponPackShop.getCurrentStock(), 0)) {
            return;
        }

        List<OrderList> orderLists = orderListService.listByComboId(String.valueOf(id));

        // 是否存在未支付订单
        boolean hasUnpaidOrder = orderLists.stream().anyMatch(item -> PayStatusEnum.UNPAID.getCode().equals(item.getPayStatus()));
        if (hasUnpaidOrder) {
            return;
        }

        // 更新礼包状态已售罄
        marCouponPackShopMapper.updateStatusById(id, CouponPackShopStatusEnum.SOLD_OUT.getCode());
    }
}




